package com.tengju.user.domain.model.archive;

import com.tengju.user.domain.shared.DomainException;
import com.tengju.user.domain.shared.DomainExceptionCode;
import com.tengju.user.domain.shared.DoubleCalculator;
import lombok.Value;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import static java.math.RoundingMode.FLOOR;

@Value
public class IdCardNo {

    String value;

    public IdCardNo(String value) {
        if (value == null) {
            throw DomainException.error(DomainExceptionCode.INVALID_DATA, "null");
        }
        this.value = value.strip();
    }


    public boolean isValid() {
        // 基础的校验，校验身份证格式是否正确
        if (!isCardNumber(value)) {
            return false;
        }

        // 检查校验码
        return checkCode(fifteen2Eighteen(value));
    }

    private boolean checkCode(String idCard) {
        String idCardBase = idCard.substring(0, 17);
        String code = genCode(idCardBase);
        return idCard.equals(idCardBase + code);
    }

    private String fifteen2Eighteen(String value) {
        if (value.length() != 15) {
            return value;
        }

        // 如果身份证顺序码是996 997 998 999，这些是为百岁以上老人的特殊编码
        // 一般 19 就行了
        String code = "19";
        String idCardBase = value.substring(0, 6) + code + value.substring(6, 15);
        return idCardBase + genCode(idCardBase);
    }

    private String genCode(String idCardBase) {
        int idCardLength = idCardBase.length();
        if (idCardLength != 17) {
            return null;
        }
        int[] factor = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        String[] verifyNumbers = new String[]{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
        int sum = 0;
        for (int i = 0; i < idCardLength; i++) {
            sum += Integer.parseInt(idCardBase.substring(i, i + 1)) * factor[i];
        }
        int index = sum % 11;
        return verifyNumbers[index];
    }

    private boolean isCardNumber(String value) {
        return value.matches("(^\\d{15}$)|(^\\d{17}(\\d|X)$)");
    }


    public int getAgeByID() {

        //过了这年的生日才算多了1周岁
        LocalDate birthday = LocalDate.parse(value.substring(6, 14), DateTimeFormatter.ofPattern("yyyyMMdd"));
        //获得出生年月日的时间戳
        long dateTimestamp = Timestamp.valueOf(birthday.atStartOfDay()).getTime();
        //获得今日的时间戳
        long todayTimestamp = System.currentTimeMillis();
        //得到两个日期相差的大体年数
        double diffDay = DoubleCalculator.divideDouble((todayTimestamp - dateTimestamp), 86400000, 10, FLOOR);
        int diffYear = DoubleCalculator.divideFloor(BigDecimal.valueOf(diffDay), BigDecimal.valueOf(365));
        //加上这个年数后得到那日的时间戳后与今日的时间戳相比
        return birthday.plusYears(diffYear).isAfter(LocalDate.now()) ? (diffYear + 1) : diffYear;
    }

    @Override
    public String toString() {
        return value;
    }
}
